<script setup lang="tsx">
import VueRouter from 'vue-router';
// TODO: 使用 tsx 时，ts 插件无法正确识别 components.d.ts 中声明的组件 type。
//    不影响 vite 编译但会导致在 vscode 中提示错误 TS2304，
//    找到原因后移除手动的组件和样式引用
import { ElMenu, ElMenuItem, ElSubMenu } from 'element-plus';
import 'element-plus/es/components/menu/style/css';
import 'element-plus/es/components/menu-item/style/css';
import 'element-plus/es/components/sub-menu/style/css';
import _ from 'lodash';
import { i18n } from '@core/i18n';

export interface MenuItemConfig {
  isMenu?: boolean,
  titleI18n?: string,
  title?: string,
  order?: number,
}
export interface SampleRouteRecord {
  name?: VueRouter.RouteRecordName | null,
  path?: string,
  redirect?: string,
  meta?: MenuItemConfig,
  children?: SampleRouteRecord[],
}
interface Props {
  title?: string,
  menuRoutes: SampleRouteRecord[],
  activePath: string,
}
const props = withDefaults(defineProps<Props>(), {
  menuRoutes: () => [],
});
type Emit = {
  (e: 'click-menu-item', subRoute: SampleRouteRecord): void,
}
const emit = defineEmits<Emit>();

const render = () => {
  return <ElMenu
    class="navigator-menu"
    default-active={props.activePath}
  >
    {{ default: () => { return [renderTitleBlock(), ...renderSubMenus(props.menuRoutes)]; } }}
  </ElMenu>;
};

const renderTitleBlock = () => {
  if (!props.title) {
    return null;
  }
  return <div class="title-block">
    <span class="title">{props.title}</span>
    <div class="divider" />
  </div>;
};

const renderSubMenus = (subMenus?: SampleRouteRecord[], parentPath = '') => {
  if (!subMenus) {
    return [];
  }
  return subMenus
    .filter((subRoute) => subRoute.meta?.isMenu)
    .sort((routeA, routeB) => {
      return (routeA.meta?.order || Number.MAX_SAFE_INTEGER) - (routeB.meta?.order || Number.MAX_SAFE_INTEGER);
    })
    .map((subRoute) => renderSubMenu(subRoute, parentPath));
};

const renderSubMenu = (subRoute: SampleRouteRecord, parentPath: string) => {
  const menuConfig = subRoute.meta as MenuItemConfig;
  const title = menuConfig.titleI18n
    ? i18n.global.t(`menu.${menuConfig.titleI18n}`)
    : menuConfig.title;
  const menuItemIndex = getMenuItemPath(subRoute, parentPath);
  const childRoutesNeedToRender = subRoute.children?.filter((childRoute) => childRoute.meta?.isMenu);

  if (_.isEmpty(childRoutesNeedToRender)) {
    return <ElMenuItem
      class="menu-item"
      index={menuItemIndex}
      onClick={() => { emit('click-menu-item', subRoute); }}
    >
      {title}
    </ElMenuItem>;
  }

  return <ElSubMenu class="sub-menu" index={menuItemIndex}>{{
    title: () => { return <span>{title}</span>; },
    default: () => { return renderSubMenus(childRoutesNeedToRender, subRoute.path); },
  }}</ElSubMenu>;
};

const getMenuItemPath = (item: SampleRouteRecord, parentPath: string) => {
  const pathToDirect = item.redirect || item.path || '';
  if (parentPath) {
    return `/${parentPath}/${pathToDirect}`;
  }
  return `/${pathToDirect}`;
};
</script>

<template>
  <render />
</template>

<style lang="scss" scoped>
.navigator-menu {
  --el-menu-item-height: 40px;
  --el-menu-item-font-size: 12px;
  --cns-main-app-el-menu-item-height: 40px;
  --cns-main-app-el-menu-item-font-size: 12px;

  &:not(.el-menu--collapse) {
    width: 197px;
    min-height: 100%;
  }
}

:deep(.title-block) {
  display: flex;
  flex-direction: column;
  width: 100%;

  .title {
    margin: 25px 18px 20px;
    font-size: 14px;
    font-weight: bold;
    line-height: 14px;
    color: #333;
  }

  .divider {
    width: 160px;
    height: 1px;
    margin: 0 15px 12px;
    background-color: #e2e5ed;
  }
}
</style>
